package cn.exempale.mscapplication.ui;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.gesture.GestureUtils;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModelProvider;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;

import cn.exempale.mscapplication.R;
import cn.exempale.mscapplication.databinding.ActivityUploadBinding;
import cn.exempale.mscapplication.dto.TaskDTO;
import cn.exempale.mscapplication.emnus.ProgressType;
import cn.exempale.mscapplication.model.db.entity.TaskEntity;
import cn.exempale.mscapplication.model.net.callback.Resource;
import cn.exempale.mscapplication.viewModel.UploadViewModel;
import cn.exempale.mscapplication.constant.BaseConstant;
import cn.exempale.mscapplication.dto.PrepareUploadDTO;
import cn.exempale.mscapplication.dto.UploadDTO;
import cn.exempale.mscapplication.emnus.StatusType;
import cn.exempale.mscapplication.utils.SliceIdGenerator;
import cn.exempale.mscapplication.vo.FileVO;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;

public class UploadActivity extends BaseActivity {

    private static final String TAG = "MainActivity";

    private ActivityUploadBinding binding;
    private UploadViewModel viewModel;
    private MutableLiveData<String> infoLiveData;
    private String taskId;
    private FileAdapter adapter;
    private MutableLiveData<Boolean> isUpload;

    private final String RESOURCE_ROOT = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_ALARMS).getAbsolutePath() + "/msc/test.wav";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_upload);
        binding.setLifecycleOwner(this);
        viewModel = new ViewModelProvider(this).get(UploadViewModel.class);
        infoLiveData = new MutableLiveData<>();
        isUpload = new MutableLiveData<>();
        isUpload.setValue(false);
        adapter = new FileAdapter(this);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            // 显示所有可用文件
            binding.button.setOnClickListener(v -> {
                AudioService.startActionAudio(this, RESOURCE_ROOT);
                this.finish();
            });
//            getFileList();
//        } else if (shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
//            // 权限ui
        } else {
            requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
        }
    }

    public void getFileList() {
        File file = new File(RESOURCE_ROOT);
        File[] files = file.listFiles();
        if (files == null) {

        }
    }

    /**
     * 同步上传测试
     */
    private void startSyncTask() {
        // 文件定位
        File file = new File(RESOURCE_ROOT);
        if (!file.exists()) {
            Toast.makeText(this, "文件查找失败", Toast.LENGTH_SHORT).show();
            updateInfo("文件查找失败");
            return;
        }// 预先上传
        PrepareUploadDTO dto = new PrepareUploadDTO();
        dto.setFile_name(file.getName());
        dto.setFile_len(String.valueOf(file.length()));
        int sliceNum = (int) (file.length() / BaseConstant.SLICE_SIZE);
        if (sliceNum == 0)
            sliceNum = 1;
        dto.setSlice_num(sliceNum);
        viewModel.prepareUpload(dto).observe(this, resource -> {
            if (resource.status == StatusType.ERROR) {
                // 预上传失败
                infoLiveData.setValue("预上传失败：" + resource.msg);
            } else {
                // 任务id
                taskId = (String) resource.data;
                String msg = "预上传成功taskId:" + taskId + "\n";
                // 保存数据库
                TaskEntity taskEntity = new TaskEntity();
                taskEntity.setTaskId(taskId);
                taskEntity.setCrateTime(new Date(Long.parseLong(dto.getTs())));
                taskEntity.setContact("18500000000");
                taskEntity.setFileName(dto.getFile_name());
                taskEntity.setProgressStatus(ProgressType.TASK.getCode());
                executor.execute(() -> taskDAO.save(taskEntity));
                // 更新进度
                infoLiveData.setValue(msg);
                // 上传处理
                syncUpload(file);
            }
        });
    }

    /**
     * 同步上传
     *
     * @param file
     */
    private void syncUpload(File file)  {
        executor.execute(() -> {
            try {
                // 总片数量
                int times = (int) (file.length() / BaseConstant.SLICE_SIZE) + 1;
                updateInfo("共" + times + "片\n");
                FileInputStream fins = new FileInputStream(file);
                SliceIdGenerator sliceIdGenerator = new SliceIdGenerator();
                byte[] slice = new byte[BaseConstant.SLICE_SIZE];
                // 切片上传
                for (int i = 0; i < times; i++) {
                    int len = fins.read(slice);
                    slice = Arrays.copyOfRange(slice, 0, len);
                    UploadDTO uploadDTO = new UploadDTO();
                    uploadDTO.setTask_id(taskId);
                    uploadDTO.setSlice_id(sliceIdGenerator.getNextSliceId());
                    Resource result = viewModel.upload(object2Map(uploadDTO), getSlicePart(slice, file));
                    if (result.status == StatusType.ERROR) {
                        updateInfo(result.msg);
                        updateDb(ProgressType.UPLOAD, false);
                        break;
                    } else if (result.status == StatusType.SUCCESS) {
                        updateInfo("第" + (i + 1) + "片上传成功\n");
                    }
                }
                fins.close();
                updateDb(ProgressType.UPLOAD, true);
                // 合并
                TaskDTO dto = new TaskDTO();
                dto.setTask_id(taskId);
                Resource margeResult = viewModel.marge(dto);
                if (margeResult.status == StatusType.ERROR) {
                    updateInfo(margeResult.msg);
                    updateDb(ProgressType.MARGE, false);
                } else {
                    updateInfo("合并成功");
                    this.finish();
                }
                updateDb(ProgressType.MARGE, true);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        });
    }

    /**
     * 更新数据库
     *
     * @param progressType 当前执行节点
     * @param isSuccess    接口执行结果
     */
    public void updateDb(ProgressType progressType, boolean isSuccess) {
        if (!isSuccess)
            // 获取失败状态
            progressType = ProgressType.getFailedType(progressType);
        TaskEntity taskEntity = taskDAO.findByTaskId(taskId);
        taskEntity.setProgressStatus(progressType.getCode());
        taskDAO.update(taskEntity);
    }

    /**
     * 文件上转对象转map
     *
     * @param dto
     * @return
     */
    public Map<String, RequestBody> object2Map(UploadDTO dto) {
        MediaType textType = MediaType.parse("text/plain");
        RequestBody appId = RequestBody.create(textType, dto.getApp_id());
        RequestBody signa = RequestBody.create(textType, dto.getSigna());
        RequestBody ts = RequestBody.create(textType, dto.getTs());
        RequestBody task = RequestBody.create(textType, dto.getTask_id());
        RequestBody sliceId = RequestBody.create(textType, dto.getSlice_id());
        Map<String, RequestBody> map = new HashMap<>();
        map.put("app_id", appId);
        map.put("signa", signa);
        map.put("ts", ts);
        map.put("task_id", task);
        map.put("slice_id", sliceId);
        return map;
    }

    /**
     * 分片数据处理
     *
     * @return
     */
    public MultipartBody.Part getSlicePart(byte[] slice, File file) {
        RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), slice);
        MultipartBody.Part body = MultipartBody.Part.
                createFormData("content", file.getName(), fileBody);
        return body;
    }


    /**
     * 更新日志进度
     *
     * @param msg
     */
    private void updateInfo(String msg) {
        // 加载错误信息
        String info = infoLiveData.getValue();
        if (info != null)
            info += msg;
        else
            info = msg;
        infoLiveData.postValue(info);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 0) {
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                getFileList();
            } else {
                Toast.makeText(this, "权限获取失败", Toast.LENGTH_SHORT).show();
                Log.e(TAG, "onRequestPermissionsResult: 为获取权限");
            }
        }
    }
}